use git2::Repository;
use std::fs;
use std::path::Path;
use wang_utils::git::{git_add, git_commit, git_tag, GitCommit};

///(message,tag)
pub fn setup_git_with_commits(flag: &str, commits: Vec<(&str, &str)>) -> anyhow::Result<String> {
    let uuid = uuid::Uuid::new_v4().to_string();
    let test_name = format!("unit_test_folder/{flag}-{uuid}");
    fs::create_dir_all(&test_name)?;
    let test_file_path = test_name.to_string() + "/1.txt";
    //git init
    let repo = Repository::init(&test_name)?;
    for commit in commits.iter().rev() {
        //修改文件
        fs::write(&test_file_path, uuid::Uuid::new_v4().to_string())?;
        //git add .
        git_add(&repo)?;
        //git commit
        git_commit(&repo, commit.0)?;
        if "" != commit.1 {
            git_tag(&repo, commit.1)?;
        }
    }
    Ok(test_name)
}

pub fn setup_git() -> anyhow::Result<String> {
    let uuid = uuid::Uuid::new_v4().to_string();
    let test_name = format!("unit_test_folder/{uuid}");
    let parent_dir = Path::new(&test_name).parent().unwrap();
    fs::create_dir_all(parent_dir)?;
    //git init
    let repo = Repository::init(&test_name)?;
    let test_file_path = test_name.to_string() + "/1.txt";
    fs::write(&test_file_path, "111")?;
    //git add .
    git_add(&repo)?;
    //git commit -m "initial commit"
    git_commit(&repo, "initial commit")?;
    //git tag v0.0.1
    git_tag(&repo, "v0.0.1")?;
    //修改文件内容
    fs::write(&test_file_path, "222")?;
    //git add .
    git_add(&repo)?;
    //git提交
    git_commit(&repo, "feat: 修改1.txt文件内容:222")?;
    //git tag v1.0.0
    git_tag(&repo, "v1.0.0")?;
    //修改文件内容
    fs::write(&test_file_path, "333")?;
    //git add .
    git_add(&repo)?;
    //git提交
    git_commit(&repo, "feat: 修改1.txt文件内容:333")?;
    Ok(test_name)
}

pub fn teardown_git(path: &str) {
    fs::remove_dir_all(path).unwrap();
}

pub fn setup_test_folder() -> String {
    let uuid = uuid::Uuid::new_v4().to_string();
    let test_name = format!("unit_test_folder/{uuid}");
    fs::create_dir_all(&test_name).unwrap();
    test_name
}

pub fn setup_with_commits_json<P: AsRef<Path>>(path: P) -> anyhow::Result<String> {
    let content = fs::read_to_string(path)?;
    let commits = serde_json::from_str::<Vec<GitCommit>>(&content)?;
    let commits: Vec<(&str, &str)> = commits
        .iter()
        .map(|c| (c.message.as_str(), c.tag.as_deref().unwrap_or("")))
        .collect();
    let test_folder = setup_git_with_commits("test_resolve", commits)?;
    Ok(test_folder)
}
